/////////////////////////////////////////////////////////////////////////
// 敌群事件中，用如下【注释】指定BOSS（主怪）
// <Boss: x>
// x：敌人在敌群中的序号，最小为1。（非enemyId）
/////////////////////////////////////////////////////////////////////////
// 1. 主怪（BOSS）的定义
/////////////////////////////////////////////////////////////////////////
//  在战斗事件第1页使用事件【指令-注释】，标签<Boss: x>来指定主怪，此处的x为敌人在敌群中的顺序号，而不是enemyId。x最小为1。
let SWDA_Game_Troop_setup = Game_Troop.prototype.setup;
Game_Troop.prototype.setup = function(troopId){
	SWDA_Game_Troop_setup.call(this, troopId);
	this.initBoss(); // 定义BOSS
	//this.setupBattlerDeadFlag();	//与事件回合无关，与敌人血量（死亡）条件相关
	this.setupBossTurn();
};

//定义【BOSS】，处理事件回合（即BOSS的个人回合）
Game_Troop.prototype.initBoss = function(){
	this._bossIds = [];
	this._currentBossTurnCount = 0; //当前值记录
};

Game_Troop.prototype.setBossId = function(id){
	if(!this._bossIds.contains(id))
		this._bossIds.push(id);
};

Game_Troop.prototype.currentBoss = function(){
	for(let i = 0; i < this._bossIds.length; i++){
		let enemy = this.members()[this._bossIds[i] - 1];
		if(!!enemy && enemy.isAlive())
			return enemy;
	}
	return null;
};

Game_Troop.prototype.hasBoss = function(){
	return !!this._bossIds && this._bossIds.length > 0;
};

Game_Troop.prototype.refreshBossTurnCount = function(){
	const boss = this.currentBoss();
	let count = 0;
	if(!!boss)
		count = boss.turnCount();
	else
		count = this.turnCount();
	if(count > this._currentBossTurnCount)
		this._currentBossTurnCount = count;
};

Game_Troop.prototype.bossTurnCount = function(){
	this.refreshBossTurnCount();
	return this._currentBossTurnCount;
};

// 重置事件状态-回合（当BOSS行动时（increaseSelfTurnCount）执行）
Game_Troop.prototype.resetEventFlagsByCount = function(){
	const pages = this.troop().pages;
    for (let i = 0; i < pages.length; i++){
        let page = pages[i];
        if (page.span === 1) {
            this._eventFlags[i] = false;
        }
    }
};



Game_Troop.prototype.setupBossTurn = function(){
	const page = this.troop().pages[0];
	const reg = /<Boss: (\d+)>/;
	page.list.forEach(function(ev){
		if([108, 408].contains(ev.code)){
			if(reg.exec(ev.parameters[0]))
				this.setBossId(Number(RegExp.$1) || 0);
		}
	}, this);
};



/////////////////////////////////////////////////////////////////////////
//事件回合总定义：BOSS的个人回合
/////////////////////////////////////////////////////////////////////////
Game_Troop.prototype.eventTurnCount = function(){
	if(this.hasDoppelgangerEnemy())	
		return this.eventDoppelgangerTurnCount();			// 分身敌人计算为所有敌人回合最小值
	else if(this.hasBoss() && Yanfly.Param.BECAISelfTurn)
		return this.bossTurnCount();
	else
		return this.turnCount();
};

// 分身敌人事件回合（条件：回合数=X 以及 所有目标个人回合数相等）
Game_Troop.prototype.eventDoppelgangerTurnCount = function(){
	const turnCountList = this.members().map((enemy) => enemy.turnCount());
	return Math.min.apply(null, turnCountList);
  };


/////////////////////////////////////////////////////////////////////////
//战斗事件条件
/////////////////////////////////////////////////////////////////////////
//除【回合数条件】和【角色/敌人HP条件】外，其余条件均为封装成函数的原始代码。
Game_Troop.prototype.meetsConditions = function(page){
    const c = page.conditions;
 	// 没有条件（不执行）
    if(this.meetsBattleEventConditionsNotSet(c))
        return false; 
	// 限次事件积满次数
	if (this._isEventTimesLimited && this.meetsTimesLimitedEventCompleted())
		return false;
	// 回合结束
    if(c.turnEnding){
    	if(!this.meetsBattleEventConditionsTurnEnd())
        	return false;
    }
	// 回合	
    if(c.turnValid){
    	if(!this.meetsBattleEventConditionsTurn(c))
    		return false;
    }
	// 敌人HP：定义在hpEventNeedDead.js
    if(c.enemyValid){
    	if(!this.meetsBattleEventConditionsEnemyHp(page))
    		return false;
    }
	// 角色人HP：定义在hpEventNeedDead.js
    if(c.actorValid){
    	if(!this.meetsBattleEventConditionsActorHp(page))
    		return false;
    }
	// 开关
    if(c.switchValid){
        if (!this.meetsBattleEventConditionsSwitch(c))
            return false;
    }
    return true;
};

Game_Troop.prototype.meetsBattleEventConditionsNotSet = function(condition){
	return !condition.turnEnding && !condition.turnValid && !condition.enemyValid && !condition.actorValid && !condition.switchValid;
};

Game_Troop.prototype.meetsBattleEventConditionsTurnEnd = function(){
	return BattleManager.isTurnEnd();
};

// 回合数条件：以事件回合为基准操作条件
Game_Troop.prototype.meetsBattleEventConditionsTurn = function(condition){
	// 补充内容为：当BOSS没有正执行行动、且BattleManager._phase不为phaseChange时，满足条件
	// 第一条件意义为：阻止事件在当前回合行动结束之前执行
	// 第二条件意义为：当战斗阶段为phaseChange时，执行强制行动会卡死
	// 卡死原因：战斗中请求了一个强制行动但phaseChange阶段无人执行，事件就会因为waitMode为action被永久阻塞
	const n = this.eventTurnCount();
    const a = condition.turnA;
    const b = condition.turnB;
    if(b === 0 && n !== a)
        return false; //固定回合数
    if(b > 0 && (n < 1 || n < a || n % b !== a % b))
        return false;
    if(this.hasDoppelgangerEnemy()){
    	if(this.isEnemyTurnCountSame())
    		return !this.hasAnyEnemyUsingItem() && BattleManager.canRunBattleEvent();
    	else
    		return false;
    }
    const boss = this.currentBoss();
    if(!!boss)
    	return !boss.isUsingItem() && BattleManager.canRunBattleEvent();	//isUsingItem：boss使用物品时不触发，// canRunBattleEvent：phaseChange阶段为false
    else
    	return BattleManager.canRunBattleEvent();
};

//敌人回合是否相等（条件：回合数=X 以及 所有敌人个人回合数相等）
Game_Troop.prototype.isEnemyTurnCountSame = function(){
	const turnCountList = this.members().map((enemy) => enemy.turnCount());
	return Math.max.apply(null, turnCountList) === Math.min.apply(null, turnCountList);
};

//是否存在对象正在执行行动，分身战中作为分身条件之一
//即所有人没有行动才可以分身
Game_Troop.prototype.hasAnyEnemyUsingItem = function(){
	return this.members().some((enemy) => enemy.isUsingItem());
};

Game_Troop.prototype.meetsBattleEventConditionsSwitch = function(condition){
 	return $gameSwitches.value(condition.switchId);
};

// 取消原本increaseTurn中，对【事件是否执行过（eventFlags）】的标签的重置。（即在increaseTurn后恢复为执行前的eventFlags）
// increaseTurn的重写意义：
//   禁止 在“战场回合数”变更（increaseTurn）时，重置【战斗事件执行标记】，以避免以下情况：
//   BOSS在某回合触发事件后，“战场回合数”更新，“事件执行标记”此时会被被重置为”未执行“，
//   由于“事件回合数”没有变化，此时仍满足事件回合条件且事件为“未执行”状态，因此事件将再次触发。
//   (该标记的重置改在BOSS的“个人回合数”变更时（increaseSelfTurnCount）)
//   分身战斗中也要还原状态，分身的判断交给个人回合数

let SWDA_Game_Troop_increaseTurn = Game_Troop.prototype.increaseTurn;
Game_Troop.prototype.increaseTurn = function(){
	const eventFlags = JsonEx.makeDeepCopy(this._eventFlags);
	SWDA_Game_Troop_increaseTurn.call(this);
	if(this.hasBoss() || this.hasDoppelgangerEnemy())
		this._eventFlags = eventFlags; //完全还原状态
};

BattleManager.canRunBattleEvent = function(){
	return this._phase !== "phaseChange";
};



// increaseSelfTurnCount的重写意义：
//   改为：当BOSS行动时（increaseSelfTurnCount），才重置事件执行标记。

// $gameTroop.hasAnyTurnCountAboveBoss()的判断（死亡的敌人中，是否存在其“个人回合数”>=当前BOSS回合数的情况）
// 若存在死亡敌人的个人回合数>=当前BOSS的个人回合数，则当前boss行动不重置标记。(即，仅当不存在死亡敌人个人回合数>=当前boss回合数时，重置标记)
// 目的是是为了防止下述特殊情况：
//   BOSS1被杀后，当前BOSS为BOSS2，
//   而BOSS2个人回合数比较低，在他回合数没有达到BOSS1的回合数（也就是当前事件回合数）时，（即$gameTroop.hasAnyTurnCountAboveBoss()为true时）
//   当前BOSS（即BOSS2）的行动会被重置事件执行标记。（但实际不应该重置事件执行标记）。
let SWDA_Game_Battler_increaseSelfTurnCount = Game_Battler.prototype.increaseSelfTurnCount;
Game_Battler.prototype.increaseSelfTurnCount = function(){
	// 强制行动不计算个人回合数
	if(!this.isForcingAction()){
		SWDA_Game_Battler_increaseSelfTurnCount.call(this);
		if(this.canResetEventFlags())
			$gameTroop.resetEventFlagsByCount();
	}
};

//重设事件标记的条件，如果是分身敌人，判断分身敌人的状态
Game_Battler.prototype.canResetEventFlags = function(){
	if(this.isEnemy() && $gameTroop.hasDoppelgangerEnemy())
		return $gameTroop.canResetEventFlagsByDoppelganger();
	else
		return this.isBossBattler() && !$gameTroop.hasAnyTurnCountAboveBoss();
};

// 分身敌人的重置事件标记条件（敌人数量>=2，所有敌人回合数相等）
Game_Troop.prototype.canResetEventFlagsByDoppelganger = function(){
	const members = this.members();
	if(members.length < 2)
		return true;
	else{
	  const count = members[0].turnCount();
	  for(let i = 1; i < members.length; i++){
		  if(members[i].turnCount() !== count)
			  return false;
	  }
	  return true;
	}
};

Game_Troop.prototype.hasAnyTurnCountAboveBoss = function(){
	return this.deadMembers().some((enemy) => enemy.turnCount() >= this._currentBossTurnCount);
};


//强制行动判断
Game_Battler.prototype.isForcingAction = function(){
	const action = this.currentAction();
	return !!action && action.isForcing();
};

//强制行动判断
Game_Action.prototype.isForcing = function(){
	return this._forcing;
};

// 判断是否是boss，计算回合数用。
Game_Battler.prototype.isBossBattler = function(){
	return false;
};

Game_Enemy.prototype.isBossBattler = function(){
	return this === $gameTroop.currentBoss();
};

/////////////////////////////////////////////////////////////////////////
// 解决执行时机问题
// 问题：
// 1. 由于BattleManager._phase = 'atb'时无法执行事件，
//    事件执行的有效阶段只有：战斗开始（start）和行动执行中（actionList和actionTargetList），
//    因此若技能效果触发了某个事件条件，而此时技能已经完成执行，则该事件会【拖到下一次有效行动开始时】才会触发。
// 2. 若存在“强制战斗行动”的指令，则会在 BattleManager._phase = 'phaseChange'阶段触发强制行动。
//    此时会因无法执行该请求而永久卡死。

// 解决方法：
// 在BOSS行动中，让任何回合条件都无效。
// 让BattleManager._phase = 'atb'时（读条）成为合法的事件执行条件，
// 让BattleManager._phase = 'phaseChange' 阶段无法执行事件。
// 
/////////////////////////////////////////////////////////////////////////
let SWDA_Game_Battler_initMembers = Game_Battler.prototype.initMembers;
Game_Battler.prototype.initMembers = function(){
	SWDA_Game_Battler_initMembers.call(this);
	this.endUseItem();
};
//是否有技能准备使用，如果有，禁止触发事件
Game_Battler.prototype.isUsingItem = function(){
	return false;
};
Game_Battler.prototype.startUseItem = function(){};
Game_Battler.prototype.endUseItem = function(){};

// 使用道具时做一个标记（this._usingItem）
// 如果敌人正在使用道具，禁止触发回合控制事件。
// 
// 此处的目的是，BOSS执行完第N回合行动后，再触发第N回合事件
let SWDA_Game_Battler_useItem = Game_Battler.prototype.useItem;
Game_Battler.prototype.useItem = function(item){
	this.startUseItem();
	SWDA_Game_Battler_useItem.call(this, item);
};

//行动执行完成后，去掉标记（this._usingItem）
let SWDA_Game_Battler_onAllActionsEnd = Game_Battler.prototype.onAllActionsEnd;
Game_Battler.prototype.onAllActionsEnd = function(){
	this.endUseItem();
	SWDA_Game_Battler_onAllActionsEnd.call(this);
};

Game_Enemy.prototype.startUseItem = function(){
	this._usingItem = true;
};

Game_Enemy.prototype.endUseItem = function(){
	this._usingItem = false;
};

Game_Enemy.prototype.isUsingItem = function(){
	return this._usingItem;
};


// 使“atb”成为合法的事件执行阶段
// 见SWDA_UpdateBattleEventPatch.js（由于必须放在鼠标指针之上，因此单独分出插件）


// 所有人正在读条
BattleManager.isATBRunning = function(){
	return this._phase === "atb";
};